﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace Microsoft.WowAddonStudio.TocEditor
{
    /// <summary>
    /// Manages the file list in the editor. A simple helper
    /// class for the Files page at 'Project properties'.
    /// </summary>
    public class FileListManager : IFileListManager
    {
        #region Private members

        private readonly List<IFileRepresentation> files;

        #endregion

        #region Lifecycle methods

        /// <summary>
        /// Creates instances of <see cref="FileListManager"/>.
        /// </summary>
        /// <param name="document">Toc document.</param>
        /// <param name="allFilesInProject">List of all files in the project.</param>
        public FileListManager(TocDocument document, IEnumerable<string> allFilesInProject)
        {
			if(document==null)
				throw new ArgumentNullException("document");
			document.DocumentFileChanged += new EventHandler(Document_DocumentFileChanged);

        	IList<string> includedInToc = document.Files.ToList();
            files=new List<IFileRepresentation>();

            foreach (var fileRelativePath in includedInToc.Union(allFilesInProject).Distinct())
            {
                files.Add(new FileRepresentation(fileRelativePath, includedInToc.Contains(fileRelativePath)));
            }
        }
        #endregion

        #region Public events and methods

        /// <summary>
        /// This event is fired when either the order of the file list, or any of
        /// its items are changed.
        /// </summary>
        public event EventHandler<FileListManagerEventArgs> OnFileListChanged;

        /// <summary>
        /// Retrieves the list of files in the order the user would like to see it
        /// in the TOC file.
        /// </summary>
        public IList<IFileRepresentation> Files
        {
            get { return files;}
        }

        /// <summary>
        /// Moves up a given element in the list.
        /// </summary>
        public void MoveUp(IFileRepresentation file)
        {
            int selectedIndex = files.IndexOf(file);

            if (selectedIndex >= 1)
            {
                files.RemoveAt(selectedIndex);
                files.Insert(selectedIndex - 1, file);
                RaiseOnFileListChangedEvent(selectedIndex-1);
            }
        }

        /// <summary>
        /// Moves down a given element in the list.
        /// </summary>
        public void MoveDown(IFileRepresentation file)
        {
            int selectedIndex = files.IndexOf(file);

            if (selectedIndex < files.Count-1)
            {
                files.RemoveAt(selectedIndex);
                files.Insert(selectedIndex + 1, file);
                RaiseOnFileListChangedEvent(selectedIndex + 1);
            }
        }

        /// <summary>
        /// Changes the state of a given element in the list. (included or
        /// not included)
        /// </summary>
        public void ChangeIncludeState(IFileRepresentation file)
        {
            if(files.IndexOf(file)>-1)
            {
                var representation = file as FileRepresentation;

            	if (representation != null)
            		representation.IsIncluded = !representation.IsIncluded;

            	RaiseOnFileListChangedEvent(files.IndexOf(file));
            }
        }
        #endregion

        #region Private member functions

		/// <summary>
		/// Raises the on file list changed event.
		/// </summary>
		/// <param name="affectedIndex">Index of the affected.</param>
        private void RaiseOnFileListChangedEvent(int affectedIndex)
        {
            if(OnFileListChanged!=null)
                OnFileListChanged(this, new FileListManagerEventArgs(this, files as IList<IFileRepresentation>, affectedIndex));
        }

		/// <summary>
		/// Handles the DocumentFileChanged event of the Document control.
		/// </summary>
		/// <param name="sender">The source of the event.</param>
		/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
		private void Document_DocumentFileChanged(object sender, EventArgs e)
		{
			RaiseOnFileListChangedEvent(-1);
		}

        #endregion
    }
}